package cn.caskm.souvenirshopsystem.service.impl;

import cn.caskm.souvenirshopsystem.constants.BizConstants;
import cn.caskm.souvenirshopsystem.domain.Result;
import cn.caskm.souvenirshopsystem.domain.dto.PageDTO;
import cn.caskm.souvenirshopsystem.domain.po.Goods;
import cn.caskm.souvenirshopsystem.domain.po.SeckillGoods;
import cn.caskm.souvenirshopsystem.domain.query.SeckillGoodsQuery;
import cn.caskm.souvenirshopsystem.domain.vo.SeckillGoodsVO;
import cn.caskm.souvenirshopsystem.exceptions.BizException;
import cn.caskm.souvenirshopsystem.mapper.SeckillGoodsMapper;
import cn.caskm.souvenirshopsystem.service.GoodsService;
import cn.caskm.souvenirshopsystem.service.SeckillGoodsService;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class SeckillGoodsServiceImpl extends ServiceImpl<SeckillGoodsMapper, SeckillGoods> implements SeckillGoodsService {

    private final GoodsService goodsService;

    @Override
    public Result<PageDTO<SeckillGoodsVO>> page(SeckillGoodsQuery query) {
        // 获取参数
        Long pageNum = query.getPageNum();
        if (pageNum == null) {
            pageNum = BizConstants.DEFAULT_PAGE_NUM;
        }
        Long pageSize = query.getPageSize();
        if (pageSize == null) {
            pageSize = BizConstants.DEFAULT_PAGE_SIZE;
        }

        // 查询数据
        Page<SeckillGoods> page = lambdaQuery()
                .like(StrUtil.isNotBlank(query.getSeckillName()), SeckillGoods::getSeckillName, query.getSeckillName())
                .eq(query.getGoodsId() != null, SeckillGoods::getGoodsId, query.getGoodsId())
                .eq(StrUtil.isNotBlank(query.getSeckillStatus()), SeckillGoods::getSeckillStatus, query.getSeckillStatus())
                .orderByDesc(SeckillGoods::getCreateTime)
                .page(new Page<>(pageNum, pageSize));

        List<SeckillGoods> seckillGoodsList = page.getRecords();
        if (CollUtil.isEmpty(seckillGoodsList)) {
            return Result.success(PageDTO.empty());
        }

        // 组装VO
        List<SeckillGoodsVO> result = buildSeckillGoodsVOList(seckillGoodsList);

        return Result.success(PageDTO.of(result, page.getPages(), page.getTotal()));
    }

    @Override
    public Result<List<SeckillGoodsVO>> getOngoingSeckillGoods() {
        LocalDateTime now = LocalDateTime.now();
        List<SeckillGoods> seckillGoodsList = lambdaQuery()
                .eq(SeckillGoods::getSeckillStatus, "1") // 进行中
                .le(SeckillGoods::getStartTime, now)
                .ge(SeckillGoods::getEndTime, now)
                .orderByAsc(SeckillGoods::getEndTime)
                .list();

        if (CollUtil.isEmpty(seckillGoodsList)) {
            return Result.success(new ArrayList<>());
        }

        // 过滤掉没有库存的商品
        seckillGoodsList = seckillGoodsList.stream()
                .filter(goods -> goods.getSeckillStock() > goods.getSoldCount())
                .collect(Collectors.toList());

        List<SeckillGoodsVO> result = buildSeckillGoodsVOList(seckillGoodsList);
        return Result.success(result);
    }

    @Override
    public Result<List<SeckillGoodsVO>> getUpcomingSeckillGoods() {
        LocalDateTime now = LocalDateTime.now();
        List<SeckillGoods> seckillGoodsList = lambdaQuery()
                .eq(SeckillGoods::getSeckillStatus, "0") // 未开始
                .gt(SeckillGoods::getStartTime, now)
                .orderByAsc(SeckillGoods::getStartTime)
                .last("LIMIT 10") // 最近10个即将开始的
                .list();

        if (CollUtil.isEmpty(seckillGoodsList)) {
            return Result.success(new ArrayList<>());
        }

        List<SeckillGoodsVO> result = buildSeckillGoodsVOList(seckillGoodsList);
        return Result.success(result);
    }

    @Override
    public Result<SeckillGoodsVO> getSeckillGoodsDetail(Integer seckillId) {
        SeckillGoods seckillGoods = getById(seckillId);
        if (seckillGoods == null) {
            throw new BizException("秒杀商品不存在");
        }

        List<SeckillGoodsVO> voList = buildSeckillGoodsVOList(Collections.singletonList(seckillGoods));
        if (CollUtil.isEmpty(voList)) {
            throw new BizException("秒杀商品信息异常");
        }

        return Result.success(voList.get(0));
    }

    @Override
    public Result<Void> createSeckillGoods(SeckillGoods seckillGoods) {
        // 验证商品是否存在
        Goods goods = goodsService.getById(seckillGoods.getGoodsId());
        if (goods == null) {
            throw new BizException("商品不存在");
        }

        seckillGoods.setCreateTime(LocalDateTime.now());
        seckillGoods.setUpdateTime(LocalDateTime.now());
        seckillGoods.setSoldCount(0);
        seckillGoods.setSeckillStatus("0"); // 默认未开始

        save(seckillGoods);
        return Result.success();
    }

    @Override
    public Result<Void> updateSeckillGoods(SeckillGoods seckillGoods) {
        if (seckillGoods.getSeckillId() == null) {
            throw new BizException("秒杀商品ID不能为空");
        }

        SeckillGoods existing = getById(seckillGoods.getSeckillId());
        if (existing == null) {
            throw new BizException("秒杀商品不存在");
        }

        seckillGoods.setUpdateTime(LocalDateTime.now());
        updateById(seckillGoods);
        return Result.success();
    }

    @Override
    public Result<Void> deleteSeckillGoods(Integer seckillId) {
        SeckillGoods seckillGoods = getById(seckillId);
        if (seckillGoods == null) {
            throw new BizException("秒杀商品不存在");
        }

        // 只能删除未开始的秒杀商品
        if (!"0".equals(seckillGoods.getSeckillStatus())) {
            throw new BizException("只能删除未开始的秒杀商品");
        }

        removeById(seckillId);
        return Result.success();
    }

    @Override
    public Result<Void> updateSeckillStatus(Integer seckillId, String status) {
        SeckillGoods seckillGoods = getById(seckillId);
        if (seckillGoods == null) {
            throw new BizException("秒杀商品不存在");
        }

        seckillGoods.setSeckillStatus(status);
        seckillGoods.setUpdateTime(LocalDateTime.now());
        updateById(seckillGoods);
        return Result.success();
    }

    /**
     * 构建秒杀商品VO列表
     */
    private List<SeckillGoodsVO> buildSeckillGoodsVOList(List<SeckillGoods> seckillGoodsList) {
        if (CollUtil.isEmpty(seckillGoodsList)) {
            return new ArrayList<>();
        }

        // 获取商品信息
        Set<Integer> goodsIds = seckillGoodsList.stream().map(SeckillGoods::getGoodsId).collect(Collectors.toSet());
        Map<Integer, Goods> goodsMap = Collections.emptyMap();
        if (CollUtil.isNotEmpty(goodsIds)) {
            List<Goods> goodsList = goodsService.lambdaQuery()
                    .in(Goods::getGoodsId, goodsIds)
                    .list();
            if (CollUtil.isNotEmpty(goodsList)) {
                goodsMap = goodsList.stream().collect(Collectors.toMap(Goods::getGoodsId, g -> g));
            }
        }

        // 组装VO
        List<SeckillGoodsVO> result = new ArrayList<>(seckillGoodsList.size());
        LocalDateTime now = LocalDateTime.now();
        
        for (SeckillGoods seckillGoods : seckillGoodsList) {
            SeckillGoodsVO vo = BeanUtil.copyProperties(seckillGoods, SeckillGoodsVO.class);
            
            // 设置商品信息
            Goods goods = goodsMap.get(seckillGoods.getGoodsId());
            if (goods != null) {
                vo.setGoodsName(goods.getGoodsName());
                vo.setGoodsImage(goods.getImage());
            }
            
            // 计算剩余库存
            vo.setRemainStock(seckillGoods.getSeckillStock() - seckillGoods.getSoldCount());
            
            // 计算倒计时
            if ("0".equals(seckillGoods.getSeckillStatus())) {
                // 未开始，计算距离开始的时间
                Duration duration = Duration.between(now, seckillGoods.getStartTime());
                vo.setCountdown(duration.getSeconds());
            } else if ("1".equals(seckillGoods.getSeckillStatus())) {
                // 进行中，计算距离结束的时间
                Duration duration = Duration.between(now, seckillGoods.getEndTime());
                vo.setCountdown(duration.getSeconds());
            } else {
                vo.setCountdown(0L);
            }
            
            result.add(vo);
        }

        return result;
    }
}
